package cn.apelx.tcc.common.domain;

import lombok.AllArgsConstructor;
import lombok.Getter;
import org.springframework.data.domain.Persistable;

import javax.persistence.*;
import java.io.Serializable;
import java.util.Map;

/**
 * tcc事务控制表
 *
 * @author apelx
 * @since 2022-05-02
 */
@Getter
@Entity
@Table(name = "tcc_transaction")
public class TccTransaction implements Persistable<String>, Serializable {

    @AllArgsConstructor
    @Getter
    public enum Status {
        INIT("事务初始化") {
            @Override
            protected boolean commit(TccTransaction tccTransaction) {
                tccTransaction.status = Status.COMMITTED;
                return true;
            }

            @Override
            protected boolean rollback(TccTransaction tccTransaction) {
                tccTransaction.status = Status.ROLLED_BACKED;
                return true;
            }
        },
        COMMITTED("已提交"),
        ROLLED_BACKED("已回滚");

        protected boolean commit(TccTransaction tccTransaction) {
            return false;
        }

        protected boolean rollback(TccTransaction tccTransaction) {
            return false;
        }

        private final String name;
    }

    protected TccTransaction() {

    }

    public TccTransaction(String xid, Status status) {
        this.xid = xid;
        this.status = status;
    }

    @Id
    private String xid;

    @Enumerated(value = EnumType.STRING)
    private Status status;

    @Override
    public String getId() {
        return this.xid;
    }

    @Override
    public boolean isNew() {
        return null == getId();
    }

    /**
     * 生成xid
     *
     * @param map
     * @return
     */
    public static String genXid(String xid, Map<String, Object> map) {
//        try...actionContextMap: {action-start-time=1651483559010, sys::prepare=createTcc, orderId=ac01444c37d64567b71a5092fb9f77c6, sys::rollback=createTccRollback, sys::commit=createTccCommit, orderPrice=38432.22, host-name=192.168.32.1, orderName=xxx1, actionName=createTcc}
        return xid + map.getOrDefault("actionName", "");
    }

    public boolean commit() {
        return this.getStatus().commit(this);
    }

    public boolean rollback() {
        return this.getStatus().rollback(this);
    }
}
